﻿using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;

namespace CrackNET.InjectedViewer.ViewModel.DebugOutput
{
    public class DebugOutputViewModel : WorkspaceViewModel
    {
        #region Fields

        const string LISTENER_NAME = "CrackNET_Listener";

        ICommand _clearLogCommand;
        ICommand _copyLogToClipboardCommand;
        string _debugOutput = String.Empty;
        bool _isLoggingOutput;

        #endregion // Fields

        #region Constructor

        public DebugOutputViewModel()
        {
            base.DisplayName = "Debug Output";
            this.IsLoggingOutput = true;
        }

        #endregion // Constructor

        #region ClearLogCommand

        public ICommand ClearLogCommand
        {
            get
            {
                if (_clearLogCommand == null)
                {
                    _clearLogCommand = new RelayCommand(
                        () => this.DebugOutput = String.Empty,
                        () => !String.IsNullOrEmpty(this.DebugOutput));
                }
                return _clearLogCommand;
            }
        }

        #endregion // ClearLogCommand

        #region CopyLogToClipboardCommand

        public ICommand CopyLogToClipboardCommand
        {
            get
            {
                if (_copyLogToClipboardCommand == null)
                {
                    _copyLogToClipboardCommand = new RelayCommand(
                        () => Clipboard.SetText(this.DebugOutput),
                        () => !String.IsNullOrEmpty(this.DebugOutput));
                }
                return _copyLogToClipboardCommand;
            }
        }

        #endregion // CopyLogToClipboardCommand

        #region DebugOutput

        public string DebugOutput
        {
            get { return _debugOutput; }
            private set
            {
                if (value == _debugOutput)
                    return;

                _debugOutput = value;

                base.OnPropertyChanged("DebugOutput");
            }
        }

        #endregion // DebugOutput

        #region IsLoggingOutput

        public bool IsLoggingOutput
        {
            get { return _isLoggingOutput; }
            set
            {
                if (value == _isLoggingOutput)
                    return;

                _isLoggingOutput = value;

                if (_isLoggingOutput)
                {
                    Debug.Listeners.Add(new InternalTraceListener(this));
                }
                else
                {
                    Debug.Listeners.Remove(LISTENER_NAME);
                }

                base.OnPropertyChanged("IsLoggingOutput");
            }
        }

        #endregion // IsLoggingOutput

        #region InternalTraceListener [nested class]

        private class InternalTraceListener : TraceListener
        {
            readonly DebugOutputViewModel _owner;

            public InternalTraceListener(DebugOutputViewModel owner)
            {
                _owner = owner;
                base.Name = DebugOutputViewModel.LISTENER_NAME;
            }
            
            public override void Write(string message)
            {
                _owner.DebugOutput += message;
            }

            public override void WriteLine(string message)
            {
                _owner.DebugOutput += message + Environment.NewLine;
            }
        }

        #endregion // InternalTraceListener [nested class]
    }
}